package com.hl.vcd.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hl.common.result.R;
import com.hl.common.utils.JwtUtils;
import com.hl.vcd.entity.CollectionRecords;
import com.hl.vcd.entity.LikeRecords;
import com.hl.vcd.entity.PlayRecords;
import com.hl.vcd.entity.Video;
import com.hl.vcd.entity.vo.CollectionRecordsDetail;
import com.hl.vcd.entity.vo.PlayRecordsDetail;
import com.hl.vcd.service.CollectionRecordsService;
import com.hl.vcd.service.LikeRecordsService;
import com.hl.vcd.service.PlayRecordsService;
import com.hl.vcd.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 朱炫达
 */
@RestController
@RequestMapping("/api/core/video_operation")
public class VideoOperationController {

    private CollectionRecordsService collectionRecordsService;
    @Autowired
    public void setCollectionRecordsService(CollectionRecordsService collectionRecordsService){
        this.collectionRecordsService = collectionRecordsService;
    }

    private LikeRecordsService likeRecordsService;
    @Autowired
    public void setLikeRecordsService(LikeRecordsService likeRecordsService){
        this.likeRecordsService = likeRecordsService;
    }

    private PlayRecordsService playRecordsService;
    @Autowired
    public void setPlayRecordsService(PlayRecordsService playRecordsService){
        this.playRecordsService = playRecordsService;
    }

    private VideoService videoService;
    @Autowired
    public void setVideoService(VideoService videoService){
        this.videoService = videoService;
    }

    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    public void setRedisTemplate(RedisTemplate<String,String> redisTemplate){
        this.redisTemplate = redisTemplate;
    }

    private String getUserIdByHeaderMap(Map<Object,Object> map){
        String uuidToken = map.get("authorization").toString();
        String uuid = JwtUtils.getUUIDByJwtToken(uuidToken);
        String loginToken = redisTemplate.opsForValue().get(uuid);
        return JwtUtils.getMemberIdByJwtToken(loginToken);
    }

    @Transactional
    @PostMapping("/video_collect/{videoId}")
    public R videoCollect(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        CollectionRecords collectionRecordsHistory = collectionRecordsService.getCollectionRecordsByUserIdAndVideoId(userId,videoId);

        if (collectionRecordsHistory == null){
            CollectionRecords collectionRecords = new CollectionRecords();
            collectionRecords.setUser_id(userId).setVideo_id(videoId);

            collectionRecordsService.addCollectionRecords(collectionRecords);
            videoService.collectionIncrement(videoId);

            return R.ok().message("收藏成功");
        }
        else {
            return R.error().message("已收藏");
        }

    }

    @Transactional
    @DeleteMapping("/video_collect_cancel/{videoId}")
    public R videoCollectCancel(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        CollectionRecords collectionRecordsHistory = collectionRecordsService.getCollectionRecordsByUserIdAndVideoId(userId,videoId);

        if (collectionRecordsHistory != null){
            collectionRecordsService.deleteCollectionRecordsByUserIdAndVideoId(userId,videoId);
            videoService.collectionDecrement(videoId);

            return R.ok().message("取消收藏成功");
        }
        else {
            return R.error().message("无收藏记录");
        }
    }

    @GetMapping("/video_collect_select/{videoId}")
    public R videoCollectSelect(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        CollectionRecords collectionRecords = collectionRecordsService.getCollectionRecordsByUserIdAndVideoId(userId, videoId);
        if (collectionRecords != null){
            return R.ok().data("hasCollectionRecords",true);
        }
        else {
            return R.ok().data("hasCollectionRecords",false);
        }
    }

    @GetMapping("/get_collection_records_detail/{current}/{size}")
    public R getCollectionRecordsDetail(@RequestHeader Map<Object,Object> map,@PathVariable Integer current,@PathVariable Integer size){
        String userId = getUserIdByHeaderMap(map);

        Page<CollectionRecordsDetail> page = new Page<>(current,size);

        IPage<CollectionRecordsDetail> collectionRecordsDetailPage = collectionRecordsService.getCollectionRecordsDetailByUserId(page,userId);
        return R.ok().data("collectionRecordsDetailPage",collectionRecordsDetailPage);
    }

    @Transactional
    @PostMapping("/video_like/{videoId}")
    public R videoLike(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        LikeRecords likeRecordsHistory = likeRecordsService.getLikeRecordsByUserIdAndVideoId(userId,videoId);

        if (likeRecordsHistory == null){
            LikeRecords likeRecords = new LikeRecords();
            likeRecords.setUser_id(userId).setVideo_id(videoId);
            likeRecordsService.addLikeRecords(likeRecords);

            videoService.likeIncrement(videoId);

            return R.ok().message("点赞成功");
        }
        else {
            return R.error().message("已点赞");
        }

    }

    @Transactional
    @DeleteMapping("/video_like_cancel/{videoId}")
    public R videoLikeCancel(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        LikeRecords likeRecordsHistory = likeRecordsService.getLikeRecordsByUserIdAndVideoId(userId,videoId);

        if (likeRecordsHistory != null){
            likeRecordsService.deleteLikeRecordsByUserIdAndVideoId(userId,videoId);
            videoService.likeDecrement(videoId);

            return R.ok().message("取消点赞成功");
        }
        else {
            return R.error().message("无点赞记录");
        }
    }

    @GetMapping("/video_like_select/{videoId}")
    public R videoLikeSelect(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        LikeRecords likeRecords = likeRecordsService.getLikeRecordsByUserIdAndVideoId(userId, videoId);

        if (likeRecords !=null){
            return R.ok().data("hasLikeRecords",true);
        }
        else{
            return R.ok().data("hasLikeRecords",false);
        }
    }

    @Transactional
    @PostMapping("/video_play/{videoId}")
    public R videoPlay(@RequestHeader Map<Object,Object> map, @PathVariable String videoId){
        String userId = getUserIdByHeaderMap(map);

        Video video = videoService.getVideoById(videoId);

        //redis中没有用户一天内的播放记录
        if (Boolean.FALSE.equals(redisTemplate.hasKey(userId + videoId))) {
            //设置用户一天内有播放记录
            redisTemplate.opsForValue().set(userId+videoId,"1",1, TimeUnit.DAYS);

            //redis中没有视频播放计数器
            if (Boolean.FALSE.equals(redisTemplate.hasKey("playing"+videoId))){
                synchronized (this){
                    //redis中没有视频播放计数器
                    if (Boolean.FALSE.equals(redisTemplate.hasKey("playing"+videoId))){
                        redisTemplate.opsForValue().set("playing"+videoId, String.valueOf(video.getPlayNumber()+1),1, TimeUnit.HOURS);

                        //设置一个500秒以后更新播放数到数据库的线程并删除redis中的计数器
                        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

                        scheduler.schedule(()->{
                            Integer playNumber = Integer.valueOf(Objects.requireNonNull(redisTemplate.opsForValue().get("playing" + videoId)));
                            Video updateVideo = new Video();
                            updateVideo.setId(videoId).setPlayNumber(playNumber);
                            videoService.updateVideoById(updateVideo);
                            redisTemplate.delete("playing"+videoId);
                        }, 10,  TimeUnit.SECONDS);

                        scheduler.shutdown();
                    }
                    else {
                        redisTemplate.opsForValue().increment("playing"+videoId);
                    }
                }
            }
            else {
                redisTemplate.opsForValue().increment("playing"+videoId);
            }

        }

        PlayRecords playRecordsHistory = playRecordsService.getPlayRecordsByUserIdAndVideoId(userId,videoId);
        if (playRecordsHistory == null){
            PlayRecords playRecords = new PlayRecords();
            playRecords.setUser_id(userId).setVideo_id(videoId);
            playRecordsService.addPlayRecords(playRecords);
        }
        else{
            playRecordsService.updatePlayRecords(playRecordsHistory);
        }

        return R.ok().message("播放记录成功");
    }

    @GetMapping("/get_play_records_detail")
    public R getPlayRecordsDetail(@RequestHeader Map<Object,Object> map){
        String userId = getUserIdByHeaderMap(map);

        List<PlayRecordsDetail> playRecordsDetailList = playRecordsService.getPlayRecordsDetailByUserId(userId);

        return R.ok().data("playRecordsDetail",playRecordsDetailList);
    }

    @DeleteMapping("/delete_play_records/{recordsId}")
    public R deletePlayRecords(@PathVariable String recordsId){
        playRecordsService.deletePlayRecordsById(recordsId);
        return R.ok().message("删除成功");
    }

    @DeleteMapping("/delete_all_play_records")
    public R deleteAllPlayRecords(@RequestHeader Map<Object,Object> map){
        String userId = getUserIdByHeaderMap(map);
        playRecordsService.deleteAllPlayRecordsByUserId(userId);
        return R.ok().message("删除成功");
    }

}
